// libcore.cpp : Defines the initialization routines for the DLL.
//

#include "stdafx.h"
#include "libcore.h"
#include <InitGuid.h>
#include "FGManager.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

//
//TODO: If this DLL is dynamically linked against the MFC DLLs,
//		any functions exported from this DLL which call into
//		MFC must have the AFX_MANAGE_STATE macro added at the
//		very beginning of the function.
//
//		For example:
//
//		extern "C" BOOL PASCAL EXPORT ExportedFunction()
//		{
//			AFX_MANAGE_STATE(AfxGetStaticModuleState());
//			// normal function body here
//		}
//
//		It is very important that this macro appear in each
//		function, prior to any calls into MFC.  This means that
//		it must appear as the first statement within the
//		function, even before any object variable declarations
//		as their constructors may generate calls into the MFC
//		DLL.
//
//		Please see MFC Technical Notes 33 and 58 for additional
//		details.
//

// ClibcoreApp

BEGIN_MESSAGE_MAP(ClibcoreApp, CWinApp)
END_MESSAGE_MAP()

//=============================================================================
BOOL AfxPostMessage(UINT message, WPARAM wParam, LPARAM lParam )
{
	CWnd* pMainWnd = AfxGetMainWnd();
	if (pMainWnd != NULL) {
		return pMainWnd->PostMessage(message, wParam, lParam);
	}

	return FALSE;
}

//=============================================================================
LRESULT AfxSendMessage( UINT message, WPARAM wParam /*= 0*/, LPARAM lParam /*= 0*/ )
{
	CWnd* pMainWnd = AfxGetMainWnd();
	if (pMainWnd != NULL) {
		return pMainWnd->SendMessage(message, wParam, lParam);
	}

	return 0;
}

//=============================================================================
LONGLONG GetPerfCounter( void )
{
	LARGE_INTEGER PerfFrequency = {0, };
	QueryPerformanceFrequency ((LARGE_INTEGER*)&PerfFrequency);
	LONGLONG		i64Ticks100ns = 0;
	if (PerfFrequency.QuadPart != 0) {
		QueryPerformanceCounter ((LARGE_INTEGER*)&i64Ticks100ns);
		i64Ticks100ns	= i64Ticks100ns * 10000000;
		i64Ticks100ns	= i64Ticks100ns / PerfFrequency.QuadPart;
	}

	return i64Ticks100ns;
}

//=============================================================================
bool IsVista()
{
	OSVERSIONINFO osver;

	osver.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );

	if (::GetVersionEx( &osver ) &&
			osver.dwPlatformId == VER_PLATFORM_WIN32_NT &&
			(osver.dwMajorVersion >= 6 ) )
		return TRUE;

	return FALSE;
}

//=============================================================================
bool LoadShaderFile( LPCTSTR lpszName, CStringA& str )
{
	TCHAR szBuf[MAX_PATH];

	if (!::GetModuleFileName (AfxGetInstanceHandle(), szBuf, MAX_PATH))
		return false;

	CPath filePath(szBuf);
	filePath.RemoveFileSpec();
	filePath.Append(_T("\\..\\shaders\\"));
	filePath.Append(lpszName);
	filePath.Canonicalize ();
	if (!filePath.FileExists())
		return false;

	CFile file;
	if (!file.Open(filePath, CFile::modeRead))
		return false;
	const INT nLen = (INT)file.GetLength();
	LPSTR p = str.GetBuffer (nLen + 1);
	if (NULL == p)
		return false;

	file.Read(p, nLen);
	str.ReleaseBuffer();
	return true;
}

//=============================================================================
CString GetCodecsPath( void )
{
	TCHAR szPath[MAX_PATH];
	::GetModuleFileName(AfxGetInstanceHandle(), szPath, MAX_PATH);
	CPath strCodecsPath(szPath);
	strCodecsPath.RemoveFileSpec();
	strCodecsPath.Append(_T("\\..\\codecs\\"));
	strCodecsPath.Canonicalize();

	return strCodecsPath;
}

// ClibcoreApp construction

ClibcoreApp::ClibcoreApp()
		: m_pAppSettings(NULL)
{
	// TODO: add construction code here,
	// Place all significant initialization in InitInstance
}


// The one and only ClibcoreApp object

ClibcoreApp theApp;


// ClibcoreApp initialization

BOOL ClibcoreApp::InitInstance()
{
	CWinApp::InitInstance();

	// add codecs path to environment variable
	DWORD dwBufSize = ::GetEnvironmentVariable (_T("PATH"), NULL, 0);
	if (dwBufSize > 0){
		LPTSTR szBuf = new TCHAR[dwBufSize + 1024];
		szBuf[0] = 0;
		::GetEnvironmentVariable (_T("PATH"), szBuf, dwBufSize);
		lstrcat (szBuf, _T(";"));
		lstrcat (szBuf, (LPCTSTR)GetCodecsPath());
		::SetEnvironmentVariable (_T("PATH"), szBuf);
		delete [] szBuf;
	}	

	return TRUE;
}

//=============================================================================
const LOP_SETTINGS& AfxGetAppSettings()
{
	const LOP_SETTINGS* psetting = theApp.GetSettings();
	ASSERT(psetting);

	return *psetting;
}

//=============================================================================
STDAPI CreateGraphBuilder2(REFCLSID clsid, HWND hwndVideo, const LOP_SETTINGS* pSettings, IGraphBuilder2** ppGB)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	// normal function body here
	theApp.SetSettings (pSettings);

	CheckPointer (ppGB, E_POINTER);
	if (!::IsWindow(hwndVideo)) {
		return E_INVALIDARG;
	}

	const LOP_SETTINGS& s = AfxGetAppSettings();
	*ppGB = NULL;
	CFGManager* pFG = NULL;

	if (clsid == LOPCSIDL_FGManagerPlayer) {		
		pFG = new CFGManagerPlayer (_T("CFGManagerPlayer"), NULL, s.SrcFilters, s.TraFilters, hwndVideo);
	} else if (clsid == LOPCSIDL_FGManagerDVD) {
		pFG = new CFGManagerDVD (_T("CFGManagerDVD"), NULL, s.SrcFilters, s.TraFilters, hwndVideo);
	} else if (clsid == LOPCSIDL_FGManagerCapture) {
		pFG = new CFGManagerCapture (_T("CFGManagerCapture"), NULL, s.SrcFilters, s.TraFilters, hwndVideo);
	} else if (clsid == LOPCSIDL_QuicktimeGraph) {
	} else if (clsid == LOPCSIDL_RealMediaGraph) {
	} else if (clsid == LOPCSIDL_ShockwaveGraph) {

	} else {
		return E_NOINTERFACE;
	}

	if (pFG != NULL){
		return pFG->QueryInterface(__uuidof(IGraphBuilder2), (PVOID*)ppGB);
	}

	return E_FAIL;
}